package org.gwt.pluginframework.plugin;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.gwt.pluginframework.common.Plugin;
import org.gwt.pluginframework.common.PluginManager;
import org.gwt.pluginframework.common.event.IPluginEvent;
import org.gwt.pluginframework.common.event.PluginEventHandler;

import com.extjs.gxt.ui.client.Style.Scroll;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.event.WindowEvent;
import com.extjs.gxt.ui.client.event.WindowListener;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.util.IconHelper;
import com.extjs.gxt.ui.client.widget.Window;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.grid.ColumnConfig;
import com.extjs.gxt.ui.client.widget.grid.ColumnModel;
import com.extjs.gxt.ui.client.widget.grid.Grid;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.extjs.gxt.ui.client.widget.toolbar.SeparatorToolItem;
import com.extjs.gxt.ui.client.widget.toolbar.ToolBar;
import com.google.gwt.user.client.ui.Widget;

public class EventConsole extends Plugin {

	private static final long serialVersionUID = -7888460434811479087L;

	protected Window window;
	
	protected ListStore<EventMessage> store;
	
	public EventConsole() {
		// store is needed because we store messages even before the plug-in is started and loaded.
		store = new ListStore<EventMessage>();
	}
		
	public void setupManifest() {
		manifest.setName("Console");
		manifest.setVersion("1.0");
	}
	
	@Override
	public void onInitialize() {
	    window = new Window();
		window.setHeading("Event console");
		window.setSize(600, 400);
		window.setScrollMode(Scroll.AUTOY);
		window.setLayout(new FitLayout());
		window.setTopComponent(createToolBar());
		window.add(createGrid());
		window.addWindowListener(new WindowListener() {
			@Override
			public void windowHide(WindowEvent we) {
				stop();
			}
		});
		
		registerEventHandler(new PluginEventHandler(PluginManager.ALL_EVENTS) {
			public void handle(IPluginEvent event) {
				String invoker = event.getInvoker() == null ? "" : event.getInvoker().getName();
				String message = event.getName() + " " + parseParameters(event.getParameters());
				
				store.add(new EventMessage(invoker, "event", message));						
			}
		});
		
		registerEventHandler(new PluginEventHandler(CustomEvents.START_EVENT_CONSOLE) {
			public void handle(IPluginEvent event) {
				start();
			}
		});
	}
	
	@Override
	public void onStart() {
		window.show();
	}
	
	protected Grid<EventMessage> createGrid() {
		List<ColumnConfig> configs = new ArrayList<ColumnConfig>();  
		  
	    ColumnConfig column = new ColumnConfig();  
	    column.setId("invoker");  
	    column.setHeader("Invoker");  
	    column.setWidth(150);  
	    configs.add(column);
	    
	    column = new ColumnConfig();  
	    column.setId("type");  
	    column.setHeader("Type");  
	    column.setWidth(50);  
	    configs.add(column);
	   
	    column = new ColumnConfig();  
	    column.setId("message");  
	    column.setHeader("Message");  
	    column.setWidth(150);  
	    configs.add(column);
	   
	    ColumnModel cm = new ColumnModel(configs); 

	    Grid<EventMessage> grid = new Grid<EventMessage>(store, cm);  
	    //grid.setStyleAttribute("borderTop", "none");  
	    grid.setAutoExpandColumn("message");  
	    //grid.setBorders(true);  
	    
	    return grid;
	}

	protected ToolBar createToolBar() {
		ToolBar toolBar = new ToolBar();    
		Button clear = new Button("Clear", IconHelper.createStyle("icon-delete"));
	    clear.addSelectionListener(new SelectionListener<ButtonEvent>() {
			public void componentSelected(ButtonEvent ce) {
				store.removeAll();
			}
	    });
	    toolBar.add(clear);  
	    toolBar.add(new SeparatorToolItem());  
	    
	    return toolBar;
	}
	
	protected String parseParameters(Map<String, Object> map) {
		StringBuffer buffer = new StringBuffer();
		
		if(map.entrySet().size() > 0) {
			buffer.append("{");
			
			for(Entry<String, Object> entry : map.entrySet()) {
				buffer.append(entry.getKey() + "=");
		
				if(entry.getValue() instanceof Widget) {
					buffer.append(entry.getValue().getClass() + "@" + entry.getValue().hashCode());
				} else {
					buffer.append(entry.getValue().toString());
				}
				
				buffer.append(",");
			}
		
			buffer.deleteCharAt(buffer.length() - 1);
			buffer.append("}");
		}
		
		return buffer.toString();
	}
}
